package nl.ViewerServer.ServerManager.DataManager.DataObjects;

import java.awt.Dimension;
import java.awt.Image;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.imageio.ImageIO;

import nl.ViewerServer.Exceptions.DataInitializationException;
import nl.ViewerServer.Exceptions.DataObjectException;

import org.apache.log4j.Logger;

public class ImageDataObject extends DataObject {
   private static Logger  log       = Logger.getLogger( ImageDataObject.class );
   private transient File imageFile = null;

   public ImageDataObject( String dataType ) {
      super( dataType );
   }

   public ImageDataObject( int dataObjectId, int lookmarkId, String location, String dataType ) {
      super( dataObjectId, lookmarkId, location, dataType );
   }

   public boolean initialize() throws DataInitializationException {
      // there should be one file in the folder specified by location (if more are present, take the first one)
      // FIX: let the location also be able to refer to a single file
      File folder = new File( location );

      if( !folder.exists() )
         throw new DataInitializationException( "DataObject location '" + location + "' is not a file or directory" );

      if( folder.isDirectory() ) {
         String[] files = new File( location ).list();
         if( files == null ) {
            throw new DataInitializationException( "Could not list files in folder '" + location + "'" );
         }
         for( int i = files.length - 1; imageFile == null && i >= 0; i-- ) {
            File f = new File( location + "/" + files[i] );

            if( f.isFile() ) {
               imageFile = f;
               log.debug( "ImageDataObject: " + f.getAbsolutePath() + "/" + f.length() );
            }
         }
      } else {
         imageFile = folder;
      }

      if( imageFile == null ) {
         throw new DataInitializationException( "No files found in data object location '" + location + "'" );
      }

      try {
         Image image = ImageIO.read( imageFile );
         if( image == null ) {
            log.error( "Could not read image " + imageFile.getAbsolutePath() );
            throw new DataInitializationException( "Could not read image " + imageFile.getAbsolutePath() );
         } else {
            int w = image.getWidth( null );
            int h = image.getHeight( null );
            this.setBounds( new Bounds( w, h, 1 ) );
         }
      }
      catch( IOException ioe ) {
         throw new DataInitializationException( "Could not read image " + imageFile.getAbsolutePath() );
      }

      log.info( "ImageDataObject initialized" );

      return true;
   }

   public static byte[] getBytesFromFile( File file ) throws IOException {
      InputStream is = new FileInputStream( file );

      // Get the size of the file
      long length = file.length();

      // Create the byte array to hold the data
      byte[] bytes = new byte[ (int)length ];

      // Read in the bytes
      int offset = 0;
      int numRead = 0;
      while( offset < bytes.length && ( numRead = is.read( bytes, offset, bytes.length - offset ) ) >= 0 ) {
         offset += numRead;
      }

      // Ensure all the bytes have been read in
      if( offset < bytes.length ) {
         throw new IOException( "Could not completely read file " + file.getName() );
      }

      // Close the input stream and return bytes
      is.close();
      return bytes;
   }

   public byte[] getPart( int resolution, int x, int y ) throws DataObjectException, IOException {
      if( imageFile == null ) {
         throw new DataObjectException( "ImageDataObject has not been initialized, or there is no data available" );
      }

      if( resolution >= resolutionParts.length ) {
         throw new DataObjectException( "Resolution " + resolution + " is not available for this data object: " + this );
      }

      Dimension p = resolutionParts[resolution];
      if( x < 0 || y < 0 || x >= p.width || y >= p.height ) {
         throw new DataObjectException( "Part " + x + ", " + y + " is not available for this resolution (" + resolution
            + ") of data object: " + this );
      }

      return getBytesFromFile( imageFile );
   }

}
